[Android][Framework]ActivityThread


前面介绍Handler机制的时候,遗留了一个问题:

创建ActivityThread的时候为主线程加入了Main Looper,那么主线程是怎么创建的呢?

ActivityThread启动

之前在介绍SystemServer启动的时候,在createSystemContext方法内做了如下操作:

private void createSystemContext() {
      // 创建系统上下文并设置主题
    ActivityThread activityThread = ActivityThread.systemMain();
    mSystemContext = activityThread.getSystemContext();
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

    final Context systemUiContext = activityThread.getSystemUiContext();
    systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}

然后跟一下systemMain方法


    public static ActivityThread systemMain() {
        // The system process on low-memory devices do not get to use hardware
        // accelerated drawing, since this can add too much overhead to the
        // process.
        if (!ActivityManager.isHighEndGfx()) {
            ThreadedRenderer.disable(true);
        } else {
            ThreadedRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
    }

    ActivityThread() {
        mResourcesManager = ResourcesManager.getInstance();
    }

所以这里并不是ActivityThread的执行入口。那么哪里才是入口呢?

回想主线程添加Looper的地方,对, main 方法才是真正的入口。那么 main 方法是怎么调用的呢?

通过搜索AOSP,发现在ActivityManagerService的startProcessLocked方法内出现了相关代码:

            // Start the process.  It will either succeed and return a result containing
            // the PID of the new process, or else throw a RuntimeException.
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            ProcessStartResult startResult;
            if (hostingType.equals("webview_service")) {
                startResult = startWebView(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, entryPointArgs);
            } else {
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, entryPointArgs);
            }

最终调用了 Process.start(android.app.ActivityThread) 方法,而后通过 socket 通信告知 Zygote进程fork子进程 ,即app进程。进程创建后将 ActivityThread 加载进去,执行 ActivityThread.main() 方法。

ActivityThread执行

public static void main(String[] args) {
    ...

    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    ...
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

final Handler getHandler() {
  return mH;
}

main方法主要创建Handler以及looper,另一件事就是调用attach(false)方法

这个attach做了什么呢?

final ApplicationThread mAppThread = new ApplicationThread();

private void attach(boolean system) {
    sCurrentActivityThread = this; // 对自己的引用
    mSystemThread = system; // 传入的bool参数,这里是false
    if (!system) {
        ViewRootImpl.addFirstDrawHandler(new Runnable() {
            @Override
            public void run() {
                ensureJitEnabled(); // 虚拟机JIT开启
            }
        });
        android.ddm.DdmHandleAppName.setAppName("",
                                                UserHandle.myUserId());
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        // 获取IActivityManager实例
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        // Watch for getting close to heap limit.
        ...
    } else {
        ...
    }
    ...
}

attach里面得到一个IActivityManager实例。

这个类从命名看就知道是个AIDL接口,通过ActivityManager源码可知

public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

private static final Singleton IActivityManagerSingleton =
        new Singleton() {
            @Override
            protected IActivityManager create() {
                  // 通过activity service拿到IBinder实例
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };

这样看

final IActivityManager mgr = ActivityManager.getService();
// 就相当于
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager mgr = IActivityManager.Stub.asInterface(b);

IBinder就要负责和AMS通信。

attach方法的下一步是

mgr.attachApplication(mAppThread);

该方法在IActivityManager声明,在ActivityManagerService实现

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
          // Find the application record that is being attached... 
          ...
        // 这里代码很多,关键在这一步
        if (app.instr != null) {
                thread.bindApplication(processName, appInfo, providers,
                        app.instr.mClass,
                        profilerInfo, app.instr.mArguments,
                        app.instr.mWatcher,
                        app.instr.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial);
            }
        ...
    }

这个IApplicationThread是ActivityThread的内部私有类,其bindApplication方法如下:

private class ApplicationThread extends IApplicationThread.Stub {
        public final void bindApplication(String processName, ApplicationInfo appInfo,
                List providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial) {

            if (services != null) {
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }

            setCoreSettings(coreSettings);

            AppBindData data = new AppBindData();
            data.processName = processName;
            ...
            sendMessage(H.BIND_APPLICATION, data);
        }
}

最后调用sendMessage。这个方法有多个重载方法,最终会调用到一个重载:

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

看到熟悉的mH心里就应该会舒口气,因为调用马上结束了。

在HandleMessage的地方,处理H.BIND_APPLICATION

case BIND_APPLICATION:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
    AppBindData data = (AppBindData)msg.obj;
    handleBindApplication(data);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;

private void handleBindApplication(AppBindData data) {
    ...
            // Continue loading instrumentation.
                  // 创建instrumentation对象
                final ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();

            final ComponentName component = new ComponentName(ii.packageName, ii.name);
            mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
            }


            // If the app is being launched for full backup or restore, bring it up in
            // a restricted environment with the base application class.
            //在这里创建了上层开发者的代码中所涉及的Applicaiton类的对象
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;

            // Do this after providers, since instrumentation tests generally start their
            // test thread at this point, and we don't want that racing.
                mInstrumentation.onCreate(data.instrumentationArgs);

                  //调Application的生命周期函数 onCreate()
                mInstrumentation.callApplicationOnCreate(app);

    ...
}

上面处理做了几个比较关键的事情:

  1. 获取instrumentation实例
  2. 获取Application对象
  3. instrumentation调用onCreate

下面具体看这几个东西。

Instrumentation

Class前的注释为:

用于实现应用程序检测代码的基类。 当开启Instrumentation运行时,该类将在任何应用程序代码之前实例化,从而允许您监视系统与应用程序之间的所有交互。

也就是说,只要开启instrumentation,就可以通过它来监视系统和Application之间的交互调用。

查看源码方法列表,的确看到很多和Activity相关的方法。详细的不在这里讲了。

看下实例化方法:

mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();

通过反射,从 data.instrumentationName.getClassName() 拿到instrumentation的name实例化。

拿到实例,对其进行init初始化:

mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);


    /*package*/ final void init(ActivityThread thread,
            Context instrContext, Context appContext, ComponentName component,
            IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
        mThread = thread;
        mMessageQueue = mThread.getLooper().myQueue();
        mInstrContext = instrContext;
        mAppContext = appContext;
        mComponent = component;
        mWatcher = watcher;
        mUiAutomationConnection = uiAutomationConnection;
    }

instrumentation内部有一个mThread对象,它由init方法初始化,这里init时就把自身(即主线程)传递给instrumentation。

下一步是调用onCreate方法

mInstrumentation.onCreate(data.instrumentationArgs);

    /**
     * Called when the instrumentation is starting, before any application code
     * has been loaded.  Usually this will be implemented to simply call
     * {@link #start} to begin the instrumentation thread, which will then
     * continue execution in {@link #onStart}.
     *
     * 

If you do not need your own thread -- that is you are writing your * instrumentation to be completely asynchronous (returning to the event * loop so that the application can run), you can simply begin your * instrumentation here, for example call {@link Context#startActivity} to * begin the appropriate first activity of the application. * * @param arguments Any additional arguments that were supplied when the * instrumentation was started. */ public void onCreate(Bundle arguments) { }

onCreate其实是个空方法,可以阅读注释了解详情。这之后调用一个最关键的方法:

mInstrumentation.callApplicationOnCreate(app);

    // 执行application.onCreate方法
    // 这个方法会在onCreate方法(上面的空方法)后立即调用。instrumentation测试程序会在那个onCreate中创建测试线程,所以要注意可能的风险
    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }

    // Application.java
    // application启动时,在任何activity,service,receiver对象创建之前调用,其实现要越快越好,比如使用懒加载。否则会影响在进程内启动第一个Activity,Service或receiver的性能。重写该方法时需要调用super.onCreate()
    @CallSuper
    public void onCreate() {
    }

所以最后就是调用到了Application的onCreate方法。

说道这个方法,提个题外话,自己在写App的时候,有时候会想用到一些App全局的变量,比较常用的就是自己继承Application实现一些方法,比如:

public class MainApplication extends Application {
    public static Context sAppContext;

    @Override
    public void onCreate() {
        super.onCreate();
        sAppContext = this;
    }
}

// 把manifest的application名称改掉


// 使用
Context context = MainApplication.sAppContext;

看了上面的过程就会理解为什么启动App后这个onCreate会最先调用。

LoadedApk

下面在了解一下上面调用时传递的app参数是怎么来的。

// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
Application app = data.info.makeApplication(data.restrictedBackupMode, null);

这个data就是封装在message里的数据,其具体数据来自AMS。但是info这个字段并不在AMS的数据中,查看data的类型,发现:

    static final class AppBindData {
        LoadedApk info;
        String processName;
        ApplicationInfo appInfo;
        List providers;
        ComponentName instrumentationName;
        Bundle instrumentationArgs;
        IInstrumentationWatcher instrumentationWatcher;
        IUiAutomationConnection instrumentationUiAutomationConnection;
        int debugMode;
        boolean enableBinderTracking;
        boolean trackAllocation;
        boolean restrictedBackupMode;
        boolean persistent;
        Configuration config;
        CompatibilityInfo compatInfo;
        String buildSerial;

        /** Initial values for {@link Profiler}. */
        ProfilerInfo initProfilerInfo;

        public String toString() {
            return "AppBindData{appInfo=" + appInfo + "}";
        }
    }

这个AppBindData也是ActivityThread的内部类,info字段是LoadedApk类型。查找info的赋值,就发生在handleBindApplication方法内,在拿到instrumentation实例前完成:

data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);

这中间的实现就不分析了,看一下LoadedApk是怎么拿到application对象的

// frameworks/base/core/java/android/app/LoadedApk.java
// Local state maintained about a currently loaded .apk. 如其名,就是当前加载的apk
    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Application app = null;

        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                initializeJavaContextClassLoader();
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
              // application还是从主线程里的instrumentation中得到的
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
            }
        }

        // Rewrite the R 'constants' for all library apks.
        ...

        return app;
    }

emmm….这个Application还是从主线程的instrumentation创造,再由instrumentation做onCreate…

总结

再整理一遍ActivityThread的main函数执行:

  • 初始化main Looper
  • 实例化ActivityThread
  • 初始化H Handler
  • 调用attach(false)方法
    • 得到IActivityManager,拿到AMS的binder
    • 调用AMS的attachApplication方法,拿到相关参数
    • 通过ApplicationThread实例作为参数,调用bindApplication方法,封装参数到data
    • H handler发送H.BIND_APPLICATION消息,把data发送到ActivityThread,从Binder切换到主线程
    • H handler在ActivityThread处理data
    • 从data.info拿到application对象,通过instrumentation调用callApplicationOnCreate(app)调用到onCreate完成application的创建。
  • Looper进入循环等待消息

其实,主线程的启动和Activity的启动时息息相关的,后面就在此基础上跟踪一下Application以及App的main Activity是如何启动的。


文章作者: Wossoneri
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明来源 Wossoneri !
评论
 上一篇
[Android][Framework]A/B system update [Android][Framework]A/B system update
Android N 之后新增一个A/B系统升级的OTA方案,最近因为有这个定制需求,所以了解了一下。仅记录一些我认为比较重要的部分。更多内容可以参考底部链接。
2018-06-01
下一篇 
[Android] Handler消息传递机制 [Android] Handler消息传递机制
今天看文章的时候看到一个对Android消息传递机制的描述,回想了一下这块的知识点,感觉有必要再细致地整理一番
2018-05-10
  目录